package be.kuleuven.cs.mume;

import org.jbox2d.collision.AABB;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.World;
import org.mt4j.MTApplication;
import org.mt4j.components.MTComponent;
import org.mt4j.components.TransformSpace;
import org.mt4j.components.visibleComponents.font.FontManager;
import org.mt4j.components.visibleComponents.font.IFont;
import org.mt4j.components.visibleComponents.shapes.MTLine;
import org.mt4j.components.visibleComponents.shapes.MTRoundRectangle;
import org.mt4j.components.visibleComponents.widgets.MTTextArea;
import org.mt4j.input.gestureAction.InertiaDragAction;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
import org.mt4j.input.inputProcessors.globalProcessors.CursorTracer;
import org.mt4j.sceneManagement.AbstractScene;
import org.mt4j.util.MTColor;
import org.mt4j.util.animation.Animation;
import org.mt4j.util.animation.MultiPurposeInterpolator;
import org.mt4j.util.math.Vector3D;
import org.mt4j.util.math.Vertex;

import advanced.physics.physicsShapes.PhysicsRectangle;
import advanced.physics.util.PhysicsHelper;
import advanced.physics.util.UpdatePhysicsAction;
import be.kuleuven.cs.mume.actions.UpdateConnLine;
import be.kuleuven.cs.mume.animations.LineRotationAnimationListener;
import be.kuleuven.cs.mume.animations.ScalingAnimation;
import be.kuleuven.cs.mume.gestures.MyDragGesture;
import be.kuleuven.cs.mume.objects.HelloWorldObject;
import be.kuleuven.cs.mume.objects.PhysicsBox;
import be.kuleuven.cs.mume.objects.PhysicsEllipse;
import be.kuleuven.cs.mume.objects.PhysicsRing;
import be.kuleuven.cs.mume.objects.PhysicsRoundedRectangle;

public class HelloWorldScene extends AbstractScene {
	private int constraintIterations = 10;
	
	/** THE CANVAS SCALE **/
	private float scale = 1;
	private float timeStep = 1.0f / (3.0f*scale);
	private MTApplication app;
	private World world;
	
	private MTComponent physicsContainer;

	public HelloWorldScene(MTApplication mtApplication, String name) {
		super(mtApplication, name);
		this.app = mtApplication;

		MTColor clearColor = new MTColor(146, 150, 188, 255);
		this.setClearColor(clearColor);
		//Show touches
		this.registerGlobalInputProcessor(new CursorTracer(mtApplication, this));
		
		float worldOffset = 10; //Make Physics world slightly bigger than screen borders
		//Physics world dimensions
		AABB worldAABB = new AABB(new Vec2(-worldOffset, -worldOffset), new Vec2((app.width)/scale + worldOffset, (app.height)/scale + worldOffset));
		Vec2 gravity = new Vec2(0, 0);
		boolean sleep = true;
		//Create the physics world
		this.world = new World(worldAABB, gravity, sleep);
		
		//Update the positions of the components according the the physics simulation each frame
		this.registerPreDrawAction(new UpdatePhysicsAction(world, timeStep, constraintIterations, scale));
		
		physicsContainer = new MTComponent(app);
		//Scale the physics container. Physics calculations work best when the dimensions are small (about 0.1 - 10 units)
		//So we make the display of the container bigger and add in turn make our physics object smaller
		physicsContainer.scale(scale, scale, 1, Vector3D.ZERO_VECTOR);
		this.getCanvas().addChild(physicsContainer);
		
		//Create borders around the screen
		this.createScreenBorders(physicsContainer);

		//HelloWorldObject rect = new HelloWorldObject(mtApplication, mtApplication.getWidth()/2, mtApplication.getHeight()/2, world, scale);
		MTColor white = new MTColor(255,255,255);

		IFont fontArial = FontManager.getInstance().createFont(app, "arial.ttf", 
				50, 	//Font size
				white,  //Font fill color
				white);	//Font outline color
		
		final MTTextArea textField = new MTTextArea(app, fontArial); 

		textField.setNoStroke(true);
		textField.setNoFill(true);
		textField.setPickable(false); //IMPORTANT, DO THIS FOR EVERY SUB-OBJECT

		textField.setText("Hello World!");
		

		float w = textField.getWidthXY(TransformSpace.GLOBAL), h =textField.getHeightXY(TransformSpace.GLOBAL);
		
		PhysicsBox rect = new PhysicsBox(new Vector3D(mtApplication.getWidth()/2, mtApplication.getHeight()/2)
			, textField.getWidthXY(TransformSpace.GLOBAL), textField.getHeightXY(TransformSpace.GLOBAL), app, world, 1f, 0f, .8f, scale);
//		HelloWorldObject rect = new HelloWorldObject(mtApplication, (mtApplication.getWidth()/2), (mtApplication.getHeight()/2), world, scale);
		PhysicsHelper.addDragJoint(world, rect, rect.getBody().isDynamic(), scale);
		rect.setFillColor(clearColor);
		rect.setNoFill(true);
		rect.setNoStroke(true);
		
		MTRoundRectangle rRect = new MTRoundRectangle(0,0, 0, textField.getWidthXY(TransformSpace.GLOBAL), textField.getHeightXY(TransformSpace.GLOBAL), 10, 10, app);
		rRect.setFillColor(clearColor);
		rRect.setNoFill(false);
		rRect.setNoStroke(false);
		rRect.setPickable(false);
		rect.addChild(rRect);
		rRect.setPositionGlobal(rect.getCenterPointGlobal());
		rect.addChild(textField);		
		textField.setPickable(false);
		textField.setPositionGlobal(rect.getCenterPointGlobal());
		
//		Animation anim = new Animation("scale", new MultiPurposeInterpolator( 0,1, 4000, 0, 1f, -1), rect);
//		anim.addAnimationListener(new LineRotationAnimationListener());
//		anim.start();
//
//
//		//rect.addGestureListener(DragProcessor.class,new MyDragGesture());
		final MTTextArea textField2 = new MTTextArea(app, fontArial); 

		textField2.setNoStroke(true);
		textField2.setNoFill(true);
		textField2.setPickable(false); //IMPORTANT, DO THIS FOR EVERY SUB-OBJECT

		textField2.setText("Hello World!");
		PhysicsEllipse rect2 = new PhysicsEllipse(textField2.getWidthXY(TransformSpace.GLOBAL)/2, textField2.getHeightXY(TransformSpace.GLOBAL)/2, 66
				, new Vector3D(mtApplication.getWidth()/2+0*400, mtApplication.getHeight()/2+0*100),  app, world, 1f, 0f, .8f, scale);
//		HelloWorldObject rect2 = new HelloWorldObject(mtApplication, (mtApplication.getWidth()/2+400), (mtApplication.getHeight()/2+100), world, scale);
		PhysicsHelper.addDragJoint(world, rect2, rect2.getBody().isDynamic(), scale);
		rect2.setFillColor(clearColor);
		rect2.setNoFill(true);
		rect2.setNoStroke(false);
		rect2.addChild(textField2);		
		textField2.setPositionGlobal(rect2.getCenterPointGlobal());
		
		final MTTextArea textField3 = new MTTextArea(app, fontArial); 

		textField3.setNoStroke(true);
		textField3.setNoFill(true);
		textField3.setPickable(false); //IMPORTANT, DO THIS FOR EVERY SUB-OBJECT

		textField3.setText("Hello World!");
		PhysicsRing rect3 = new PhysicsRing(new Vector3D(mtApplication.getWidth()/2+0*400, mtApplication.getHeight()/2+0*100)
		, (float) Math.sqrt(w*w+h*h)/4, app, world, 1f, 0f, .8f, scale);
//		HelloWorldObject rect2 = new HelloWorldObject(mtApplication, (mtApplication.getWidth()/2+400), (mtApplication.getHeight()/2+100), world, scale);
		PhysicsHelper.addDragJoint(world, rect3, rect3.getBody().isDynamic(), scale);
		rect3.setFillColor(clearColor);
		rect3.setNoFill(true);
		rect3.addChild(textField3);		
		textField3.setPositionGlobal(rect3.getCenterPointGlobal());
		
		final MTTextArea textField4 = new MTTextArea(app, fontArial); 

		textField4.setNoStroke(true);
		textField4.setNoFill(true);
		textField4.setPickable(false); //IMPORTANT, DO THIS FOR EVERY SUB-OBJECT

		textField4.setText("Hello World!");
		PhysicsRoundedRectangle rect4 = new PhysicsRoundedRectangle(textField4.getWidthXY(TransformSpace.GLOBAL), textField4.getHeightXY(TransformSpace.GLOBAL), 10, 1
				, new Vector3D(mtApplication.getWidth()/2+0*400, mtApplication.getHeight()/2+0*100),  app, world, 1f, 0f, .8f, scale);
//		HelloWorldObject rect2 = new HelloWorldObject(mtApplication, (mtApplication.getWidth()/2+400), (mtApplication.getHeight()/2+100), world, scale);
		PhysicsHelper.addDragJoint(world, rect4, rect4.getBody().isDynamic(), scale);
		rect4.setFillColor(clearColor);
		rect4.setNoFill(true);
		rect4.setNoStroke(false);
		rect4.addChild(textField4);		
		textField4.setPositionGlobal(rect4.getCenterPointGlobal());

		//rect2.addGestureListener(DragProcessor.class,new InertiaDragAction());
		
		MTLine connectLine = new MTLine(mtApplication, new Vertex(rect.getCenterPointGlobal()), new Vertex(rect2.getCenterPointGlobal()));
		
		connectLine.setStrokeWeight(3f);
		connectLine.setStrokeColor(MTColor.WHITE);
		connectLine.setPickable(false);
		
		MTLine connectLine2 = new MTLine(mtApplication, new Vertex(rect3.getCenterPointGlobal()), new Vertex(rect2.getCenterPointGlobal()));
		
		connectLine2.setStrokeWeight(3f);
		connectLine2.setStrokeColor(MTColor.WHITE);
		connectLine2.setPickable(false);	

		
		MTLine connectLine3 = new MTLine(mtApplication, new Vertex(rect3.getCenterPointGlobal()), new Vertex(rect4.getCenterPointGlobal()));
		
		connectLine3.setStrokeWeight(3f);
		connectLine3.setStrokeColor(MTColor.WHITE);
		connectLine3.setPickable(false);	
		
		physicsContainer.addChild(connectLine);
		physicsContainer.addChild(connectLine2);
		physicsContainer.addChild(connectLine3);
		physicsContainer.addChild(rect);
		physicsContainer.addChild(rect2);
		physicsContainer.addChild(rect3);
		physicsContainer.addChild(rect4);
		
		this.registerPreDrawAction(new UpdateConnLine(rect,rect2,connectLine));
		this.registerPreDrawAction(new UpdateConnLine(rect3,rect2,connectLine2));
		this.registerPreDrawAction(new UpdateConnLine(rect3,rect4,connectLine3));
	}
	
	private void createScreenBorders(MTComponent parent){
		//Left border 
		float borderWidth = 50f;
		float borderHeight = app.height;
		Vector3D pos = new Vector3D(-(borderWidth/2f) , app.height/2f);
		PhysicsRectangle borderLeft = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
		borderLeft.setName("borderLeft");
		parent.addChild(borderLeft);
		//Right border
		pos = new Vector3D(app.width + (borderWidth/2), app.height/2);
		PhysicsRectangle borderRight = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
		borderRight.setName("borderRight");
		parent.addChild(borderRight);
		//Top border
		borderWidth = app.width;
		borderHeight = 50f;
		pos = new Vector3D(app.width/2, -(borderHeight/2));
		PhysicsRectangle borderTop = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
		borderTop.setName("borderTop");
		parent.addChild(borderTop);
		//Bottom border
		pos = new Vector3D(app.width/2 , app.height + (borderHeight/2));
		PhysicsRectangle borderBottom = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
		borderBottom.setName("borderBottom");
		parent.addChild(borderBottom);
	}
	
	
	
	
	
	@Override
	public void init() {}
	@Override
	public void shutDown() {}
}
